#pragma once

#include "MyControls/PlayerImpl.h"
#include "MyFC/Event.h"
#include "MyViews/ZoomBench.h"

namespace My {

class DLL_API SequenceView : 
		public ZoomBench, 
		public PlayerImpl, 
		public EventListener, ///< subclass should subscribe itself on sequence's events
		protected OffscreenManager ///< subclass should implement GetOffscreenDC()
{
public:
	class Event;
	class FramerateChange;
public:
	SequenceView();
	virtual ~SequenceView();
	bool IsEmpty() const;
	/// sometimes timer is stopped frequently even in play mode due to 
	/// inability of painter to provide frames with requested framerate
	bool IsTimerStopped() { return m_nTimer == 0; }
public: //Time Controls
	int GetPlayTimerDelay() const { return int(1000.f / m_PlayFramerate); }
	void SetPlayTimerDelay(int msec) { SetFramerate(1000.f / msec); }
	float GetFramerate() const { return m_PlayFramerate; }
	void SetFramerate(float fps);
	DECLARE_PLAYER_COMMANDS()

public: //EventDispatcher interface
	using EventDispatcher::Attach;
	using EventDispatcher::Detach;
	//not using CWnd's Attach and Detach

public: //EventListener interface
	virtual void ProcessEvent(My::Event &);

protected:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	virtual void PostNcDestroy() { } ///< do nothing since view is allocated not from heap

protected:
	virtual afx_msg void OnTimer(UINT nIDEvent); ///< subclass may overload the method to skip TimeStep when previous frame is not displayed
protected:
	DECLARE_MESSAGE_MAP()

protected: //ZoomBench interface
	virtual bool GetDoubleBuffering() const { return false; }
	virtual OffscreenManager & GetOffscreenManager() { return * this; }
	virtual void PaintImageRect(CDC * pDC, CRect const & rClient, CRect const & rImage) = 0; ///< more convinient than PaintRect
	virtual void InvalidateBuffer() = 0;
	virtual void EraseBuffer() = 0;
private:
	virtual void PaintRect(CDC * pDC, const CRect & rect);

protected: //Player impl.
	virtual void StartTimer();
	virtual void StopTimer();
	//virtual Sequence * GetSequence() const; //must be provided by subclass

private:
	void WriteSettings();
	void ReadSettings();

	using ZoomBench::Invalidate;
private:
	float m_PlayFramerate;
	UINT m_nTimer;
};

// Events:
class SequenceView::Event : public My::Event {
public:
	SequenceView & m_SequenceView;
public:
	Event(SequenceView & v) : m_SequenceView(v) { }
};

class SequenceView::FramerateChange : public SequenceView::Event {
public:
	FramerateChange(SequenceView & v) : Event(v) { }
};

} //namespace My
